const fs = require('fs')

const utils = require(process.cwd() + '/src/utils/index')
const config = require(process.cwd() + '/src/config/config')
const autotilesOptions = require(process.cwd() + '/src/config/autotilesOptions')

const Tile = require('./object/tile')
const Autotile = require('./object/autotile')

// 环境
class Env {
  constructor() {
    this.initData()
  }
  
  // 初始化数据
  initData () {
    this.name = ''
    // 每一行的图块数
    this.colNum = 8
    // 初始化图集部分每一块的大小
    this.tilesWidth = 32
    this.tilesHeight = 32
    // 所有对象
    this.objects = [],
    // 添加进来的Autotile对应的对象索引
    this.autotiles = [],
    // 添加进来的普通图块对应的对象索引
    this.tiles = []
  }
  
  // 从文件中初始化Env
  async init (name) {
    const envPath = config.envPath + name + '.json'
    
    try {
      let data = await fs.promises.readFile(envPath)
      data = JSON.parse(data)
      this.setEnv(data)
      // 数据读取到后必须进行解压
      await this.unzip()
    }
    catch (e) {
      // 文件中不存在,需要自己创建
      this.name = name
    }

  }
  
  // 保存到指定文件
  async save () {
    // 保存前必须进行压缩
    this.zip()
    // 将新数据保存入文件
    const envPath = config.envPath + this.name + '.json'
    const buffer = JSON.stringify(this)
    await fs.promises.writeFile(envPath, buffer)
  }
  
  // 同步Env数据
  setEnv (data) {
    for (let key in data) {
      this[key] = data[key]  
    }
  }
  
  // 同步图块数据
  async setEnvTiles (tileset) {
    // 获取tiles开始的索引
    let objectStartIndex = typeof this.tiles[0] === 'number' ? this.tiles[0] : this.objects.length
    // 不匹配任何图集的情况处理
    if (tileset === '') {
      // 清空tiles字段
      this.tiles = []
      // 删除tiles对应的的object
      this.objects = this.objects.slice(0, objectStartIndex)
      return
    }
    
    // 根据图集名称,读取图集文件
    const tilesPath = config.tilesetsPath + tileset + '.json'
    let tilesData = await fs.promises.readFile(tilesPath)
    tilesData = JSON.parse(tilesData)
    
    // 将图块大小,列数进行同步
    this.colNum = tilesData.colNum
    this.tilesWidth = tilesData.itemWidth
    this.tilesHeight = tilesData.itemHeight
    
    // 同步图集
    const list = tilesData.list
    const len = list.length
    let envTilesList = []
    let envObjectsList = []
    for (let i = 0; i < len; i++) {
      const tile = list[i]
      let envTile = new Tile(tile.id)
      envObjectsList.push(envTile)
      envTilesList.push(objectStartIndex + i)
    }
    // 覆盖tiles索引
    this.tiles = envTilesList
    // 对象集合并
    this.objects = this.objects.slice(0, objectStartIndex).concat(envObjectsList)
  }
  
  // 添加/删去Autotile
  async autotileTrigger (autotile) {
    // 创建示例Autotile
    const tempAutotile = new Autotile(autotile)
    await tempAutotile.getDetail()
    
    const autotileNum = autotilesOptions.rules.length
    // autotile的存在性检测
    const index = this.objects.findIndex(obj => obj.autotile === autotile)
    
    if (index >= 0) {
      // 存在,则删去
      const autotileIndex = this.autotiles.indexOf(index)
      this.objects.splice(index, autotileNum)
      const deletedIndex = this.autotiles.splice(autotileIndex, 1)
      // 因为删去了多个Autotile对象,图块对象索引要整体前置,Autotile对象索引要看情况前置
      this.autotileChangeIndex(true, deletedIndex[0])
    }
    else {
      // 不存在,则添加
      let autotileObjectsList = []
      for (let i = 0; i < autotileNum; i++) {
        let envAutotile = new Autotile(autotile)
        await envAutotile.getDetail(i)
        autotileObjectsList.push(envAutotile)          
      }
      this.objects = autotileObjectsList.concat(this.objects)
      // 因为添加了多个Autotile对象,图块对象索引要整体后置,Autotile对象索引也要整体后置
      this.autotileChangeIndex(false)
      // 之后再添加新的Autotile对象索引
      this.autotiles.unshift(0)
    }
  }
  
  /*
    由于Autotile发生了增减,调整索引数组
    isPrev 是否是减掉Autotile,为true时,发生了Autotile删减,为false,发生了Autotile插入
    changeIndex isPrev为true是才需要,删去对象位置
  */
  autotileChangeIndex (isPrev = false, changeIndex = 0) {
    const autotileNum = autotilesOptions.rules.length
    const tilesLen = this.tiles.length
    const autotilesLen = this.autotiles.length
    for (let i = 0; i < tilesLen; i++) {
      if (isPrev) {
        this.tiles[i] = this.tiles[i] - autotileNum
      }
      else {
        this.tiles[i] = this.tiles[i] + autotileNum
      }
    }
    for (let i = 0; i < autotilesLen; i++) {
      if (isPrev) {
        if (changeIndex < this.autotiles[i]) {
          this.autotiles[i] = this.autotiles[i] - autotileNum
        }
      }
      else {
        this.autotiles[i] = this.autotiles[i] + autotileNum
      }
    }
  }
  
  // 解压数据,返回前端可以识别的资源地址
  async unzip () {
    const len = this.objects.length
    for (let i = 0; i < len; i++) {
      // 串行执行,避免过多次读取数据
      await Tile.unzip(this.objects[i])
      console.log(this.objects[i].src)
    }
  }
  
  // 压缩数据
  zip () {
    const len = this.objects.length
    for (let i = 0; i < len; i++) {
      // 串行执行,避免过多次读取数据
      Tile.zip(this.objects[i])
    }
  }
}

module.exports = Env